/*
 * @(#)CNIHeader.java	1.12 06/10/10
 *
 * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.  
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
 *   
 * This program is free software; you can redistribute it and/or  
 * modify it under the terms of the GNU General Public License version  
 * 2 only, as published by the Free Software Foundation.   
 *   
 * This program is distributed in the hope that it will be useful, but  
 * WITHOUT ANY WARRANTY; without even the implied warranty of  
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
 * General Public License version 2 for more details (a copy is  
 * included at /legal/license.txt).   
 *   
 * You should have received a copy of the GNU General Public License  
 * version 2 along with this work; if not, write to the Free Software  
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
 * 02110-1301 USA   
 *   
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
 * Clara, CA 95054 or visit www.sun.com if you need additional  
 * information or have any questions. 
 *
 */

package runtime;
import consts.Const;
import jcc.Util;
import util.*;
import components.*;
import vm.*;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;

public class CNIHeader extends HeaderDump{

    public CNIHeader( ){
	super( '_' );
    }

    private boolean
    generateNatives( MethodInfo methods[], boolean cplusplusguard ){
	if ( methods == null ) return false;
	boolean anyMethods = false;
	for ( int i =0; i < methods.length; i++ ){
	    MethodInfo m = methods[i];
	    if ( (m.access&Const.ACC_NATIVE) == 0 ) continue;
	    if ( cplusplusguard && ! anyMethods ){
		o.println("#ifdef __cplusplus\nextern \"C\"{\n#endif");
		anyMethods = true;
	    }
	    String methodsig = m.type.string;
	    o.println("/*");
	    o.println(" * Class:	"+className);
	    o.println(" * Method:	"+m.name.string);
	    o.println(" * Signature:	"+methodsig);
	    o.println(" */");

	    //
	    // decide whether to use long name or short.
	    // we use the long name only if we find another
	    // native method with the same short name.
	    //
	    String nameParams = null;
	    for ( int j =0; j < methods.length; j++ ){
		MethodInfo other = methods[j];
		if ( (other.access&Const.ACC_NATIVE) == 0 ) continue;
		if ( other == m ) continue; // don't compare with self!
		if ( other.name.string.equals( m.name.string ) ){
		    nameParams = methodsig;
		    break;
		}
	    }
	    // print return type and name.
	    o.print("CNIEXPORT CNINativeMethod ");
	    String name =
		Util.convertToJNIName( className, m.name.string, nameParams );
	    name = "CNI" + name.substring(5);
	    o.println( name + ";");
	}
	if ( cplusplusguard && anyMethods ){
	    o.println("#ifdef __cplusplus\n}\n#endif");
	    return true;
	}
	return false;
    }

    private void prolog(){
	o.println("/* DO NOT EDIT THIS FILE - it is machine generated */\n" +
	    "#include \"javavm/include/cni.h\"");
	o.println("/* Header for class "+className+" */\n");
	String includeName = "_CVM_CNI"+strsub(className,CDelim);
	o.println("#ifndef "+includeName);
	o.println("#define "+includeName);
    }
    private void epilog(){
	o.println("#endif");
    }

    synchronized public boolean
    dumpHeader( ClassInfo c, PrintStream outfile ){
	boolean didWork;
	o = outfile;
	className = c.className;
	prolog();
	didWork = generateConsts( Util.convertToClassName( c.className ), c.fields );
	didWork |= generateNatives( c.methods, true );
	epilog();
	return didWork;
    }

    synchronized public boolean
    dumpExternals( ClassInfo c, PrintStream outfile ){
	boolean didWork;
	o = outfile;
	className = c.className;
	didWork = generateNatives( c.methods, false );
System.err.println("CNIHeader " + className + " didWork " + didWork);
	return didWork;
    }
}
